﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace java.util
{
    public class BlockingQueue<T> : IEnumerable<T>
    {
        public BlockingQueue()
        {
            _queue = new Queue<T>();
            maxCount = 0;
        }

        public BlockingQueue(int capacity)
        {
            _queue = new Queue<T>(capacity);
            maxCount = capacity;
        }

        public int maxCount = 0;
        private int _count = 0;
        private Queue<T> _queue = null;


        public T Peek()
        {
            lock (_queue)
            {
                return _queue.FirstOrDefault();
            }
        }

        public T Take()
        {
            lock (_queue)
            {
                while (_count <= 0) Monitor.Wait(_queue);
                _count--;
                T elt = _queue.Dequeue();
                if (maxCount>0) Monitor.Pulse(_queue);
                return elt;
            }
        }

        public void Put(T data)
        {
            if (data == null) throw new ArgumentNullException("data");
            lock (_queue)
            {
                while (maxCount>0 && _count >= maxCount) Monitor.Wait(_queue);
                _queue.Enqueue(data);
                _count++;
                Monitor.Pulse(_queue);
            }
        }

        public int Count
        {
            get
            {
                return _queue.Count;
            }
        }

        #region IEnumerable<T> Members

        public IEnumerator<T> GetEnumerator()
        {
            return _queue.GetEnumerator();
        }

        #endregion

        #region IEnumerable Members

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return _queue.GetEnumerator();
        }

        #endregion
    }
}
